package com.aqie.appletserver.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.aqie.appletserver.bean.request.NewsRequest;
import com.aqie.appletserver.bean.request.SearchNewsRequest;
import com.aqie.appletserver.bean.request.VoiceRequest;
import com.aqie.appletserver.bean.request.WordRequest;
import com.aqie.appletserver.bean.response.*;
import com.aqie.appletserver.context.TokenContext;
import com.aqie.appletserver.service.IBaiduApiService;
import com.aqie.appletserver.utils.Base64Util;
import com.aqie.appletserver.utils.ConnUtil;
import com.aqie.appletserver.utils.FileUtils;
import com.aqie.appletserver.utils.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;

import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED;
import static org.springframework.http.MediaType.APPLICATION_JSON;

@Service
@Slf4j
public class BaiduApiService implements IBaiduApiService {

    @Autowired
    private RestTemplate restTemplate;

    @Value("${file.localUploadPath}")
    private String FILE_SAVE_PATH ;

    @Value("${file.staticUploadPath}")
    private String STATIC_UPLOAD_PATH; // "/upload/"

    @Value("${file.serverUrl}")
    private String SERVER_URL;

    // 果蔬识别
    private String INGREDIENT = "https://aip.baidubce.com/rest/2.0/image-classify/v1/classify/ingredient";

    // 通用图片识别
    private String COMMON_PICTURE = "https://aip.baidubce.com/rest/2.0/image-classify/v2/advanced_general";

    // 文本审核
    private String TEXT_CENSOR = "https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined";

    // 文本纠错
    private String TEXT_CORRECTION = "https://aip.baidubce.com/rpc/2.0/nlp/v1/ecnet";

    // 通用票据识别
    private String RECEIPT = "https://aip.baidubce.com/rest/2.0/ocr/v1/receipt";

    // 新闻摘要
    private String NEWS_SUMMARY = "https://aip.baidubce.com/rpc/2.0/nlp/v1/news_summary";

    // 红酒
    private String RED_WINE = "https://aip.baidubce.com/rest/2.0/image-classify/v1/redwine";

    // 食物
    private String FOOD = "https://aip.baidubce.com/rest/2.0/image-classify/v2/dish";

    // 1.生成文章
    private String GEN_ARTICLE = "https://aip.baidubce.com/rest/2.0/nlp/v1/gen_article";

    // 热点发现
    private String HOT_LIST = "https://aip.baidubce.com/rpc/2.0/creation/v1/hot_list/domain";

    // 事件脉络
    private String VEIN_LIST = "https://aip.baidubce.com/rpc/2.0/creation/v1/event/vein_list";
    // 智能春联
    private String COUPLETS = "https://aip.baidubce.com/rpc/2.0/creation/v1/couplets";
    // 智能写诗
    private String POEM = "https://aip.baidubce.com/rpc/2.0/creation/v1/poem";
    // 图文生成
    private String CREATE_VIDPRESS = "https://aip.baidubce.com/rest/2.0/nlp/v1/create_vidpress";
    // 热点发现 行业
    private String HOT_LIST_ADVANCED = "https://aip.baidubce.com/rpc/2.0/creation/v1/hot_list_advanced/domain";
    // 热点发现 地域
    private String HOT_LIST_ADVANCED_LOCATION = "https://aip.baidubce.com/rpc/2.0/creation/v1/hot_list_advanced/location";

    // 事件脉络检索
    private String VEIN_LIST_SEARCH = "https://aip.baidubce.com/rpc/2.0/creation/v1/event/vein_list_search";

    // 新闻资讯检索
    private String SEARCH_NEWS = "https://aip.baidubce.com/rpc/2.0/creation/v1/search_news";


    // todo 智能招聘  https://ai.baidu.com/ai-doc/NLP/rkbhl8n8n


    // Content-Type	application/json
    @Override
    public VoiceResponse speechToText(VoiceRequest request, String token) throws IOException {
        byte[] content = getFileContent(request.getFILENAME());
        String speech = base64Encode(content);

        JSONObject json = new JSONObject();
        json.put("format", request.getFORMAT());
        json.put("rate", request.getRATE());
        json.put("channel", 1);
        json.put("cuid", ConnUtil.urlEncode(request.getCUID()));
        json.put("dev_pid", request.getDEV_PID());
        json.put("token", token);
        json.put("len", content.length);
        json.put("speech", speech);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(APPLICATION_JSON);
        HttpEntity<String> requestEntity = new HttpEntity<>(json.toString(), headers);


        HttpMethod method = HttpMethod.POST;
        ResponseEntity<VoiceResponse> response = restTemplate.exchange(request.getURL(), method, requestEntity, VoiceResponse.class);
        //log.info("response: {}", response);
        return  response.getBody();
    }

    /**
     * application/x-www-form-urlencoded
     * 要求base64编码后大小不超过4M，最短边至少15px，最长边最大4096px,支持jpg/png/bmp格式。
     * 注意：图片需要base64编码、去掉编码头（data:image/jpg;base64,）后，再进行urlencode。
     * @return
     */
    @Override
    public FruitVegetablesResponse identifyFruitsAndVegetables(String filePath) throws IOException {
        HttpEntity<MultiValueMap<String, String>> requestEntity = getMultiValueMapHttpEntity(filePath);
        INGREDIENT = INGREDIENT + "?access_token=" + TokenContext.getToken();
        ResponseEntity<FruitVegetablesResponse> response =
                restTemplate.postForEntity(INGREDIENT, requestEntity, FruitVegetablesResponse.class);
        //log.info("response, {}", response);
        return response.getBody();
    }

    // Content-Type为application/x-www-form-urlencoded，然后通过urlencode格式化请求体
    @Override
    public CommonPictureResponse commonObjectAndSceneRecognition(String filePath) throws Exception {
        byte[] imgData = FileUtils.readFileByBytes(filePath);
        String imgStr = Base64Util.encodeBase64(imgData);
        //log.info("imgStr: {}", imgStr);
        /*String imgParam = URLEncoder.encode(imgStr, StandardCharsets.UTF_8);
        log.info("imgPar: {}", imgParam);*/

        MultiValueMap<String, String> postParameters = new LinkedMultiValueMap<>();
        postParameters.add("image", imgStr);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(APPLICATION_FORM_URLENCODED);

        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(postParameters, headers);
        COMMON_PICTURE = COMMON_PICTURE + "?access_token=" + TokenContext.getToken();
        ResponseEntity<CommonPictureResponse> response =
                restTemplate.postForEntity(COMMON_PICTURE, requestEntity, CommonPictureResponse.class);
        //log.info("response, {}", response);
        return response.getBody();
    }

    // 官方 Demo实现
    @Override
    public CommonPictureResponse commonObjectAndSceneRecognition2(String filePath) throws Exception{
        byte[] imgData = FileUtils.readFileByBytes(filePath);
        String imgStr = Base64Util.encodeBase64(imgData);
        String imgParam = (String) URLEncoder.encode(imgStr, "UTF-8");
        //log.info("imgParam: {}", imgParam);
        String param = "image=" + imgParam;

        String result = HttpUtil.post(COMMON_PICTURE, TokenContext.getToken(), param);
        //log.info("result {}", result);
        CommonPictureResponse response = JSON.parseObject(result, new TypeReference<CommonPictureResponse>() {
        });
        return response;
    }


    /**
     * 传入单个图片 返回处理后图片
     * Content-Type为application/x-www-form-urlencoded，然后通过urlencode格式化请求体
     * @param filePath 本地图片完整路径 接口地址
     * @param apiUrl
     * @return
     * @throws Exception
     */
    @Override
    public PictureResponse handleImage(String filePath, String apiUrl) throws Exception{
        HttpEntity<MultiValueMap<String, String>> requestEntity = getMultiValueMapHttpEntity(filePath);
        apiUrl = apiUrl + "?access_token=" + TokenContext.getToken();
        ResponseEntity<PictureResponse> response =
                restTemplate.postForEntity(apiUrl, requestEntity, PictureResponse.class);

        // 获取文件扩展名
        String ext = FileUtils.ext(filePath);
        String filename = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + (int) (Math.random() * 1000) + "."
                + ext;
        String newFilePath = FILE_SAVE_PATH + filename;
        if(response.getBody() != null){
            boolean b = Base64Util.Base64ToImage(response.getBody().getImage(), newFilePath);
            if(b) {
                response.getBody().setImagePath(SERVER_URL + STATIC_UPLOAD_PATH + filename);
                response.getBody().setImage("");
            }

        }

        return response.getBody();
    }

    // Content-Type	application/json
    @Override
    public TextCorrectionResponse textCorrect(String text) {
        TEXT_CORRECTION = TEXT_CORRECTION + "?access_token=" + TokenContext.getToken()+ "&charset=UTF-8";
        JSONObject json = new JSONObject();
        json.put("text", text);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(APPLICATION_JSON);
        HttpEntity<String> requestEntity = new HttpEntity<>(json.toString(), headers);

        ResponseEntity<TextCorrectionResponse> response =
                restTemplate.postForEntity(TEXT_CORRECTION, requestEntity, TextCorrectionResponse.class);
        //log.info("response, {}", response);
        return response.getBody();
    }

    // Content-Type	application/json
    @Override
    public CommonTextResponse newsSummery(NewsRequest request) {
        NEWS_SUMMARY = NEWS_SUMMARY + "?access_token=" + TokenContext.getToken()+ "&charset=UTF-8";
        JSONObject json = new JSONObject();
        json.put("title", request.getTitle());
        json.put("content", request.getContent());
        json.put("max_summary_len", request.getMaxSummaryLen());

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(APPLICATION_JSON);
        HttpEntity<String> requestEntity = new HttpEntity<>(json.toString(), headers);

        ResponseEntity<CommonTextResponse> response =
                restTemplate.postForEntity(NEWS_SUMMARY, requestEntity, CommonTextResponse.class);
        //log.info("response, {}", response);
        return response.getBody();
    }

    // 传入单个图片返回 文字
    @Override
    public ReceiptResponse receipt(String filePath) throws IOException {
        HttpEntity<MultiValueMap<String, String>> requestEntity = getMultiValueMapHttpEntity(filePath);
        RECEIPT = RECEIPT + "?access_token=" + TokenContext.getToken();
        ResponseEntity<ReceiptResponse> response =
                restTemplate.postForEntity(RECEIPT, requestEntity, ReceiptResponse.class);
        //log.info("response, {}", response);
        return response.getBody();
    }

    // 获取红酒信息
    @Override
    public WineResponse wine(String filePath) throws IOException {
        HttpEntity<MultiValueMap<String, String>> requestEntity = getMultiValueMapHttpEntity(filePath);
        RED_WINE = RED_WINE + "?access_token=" + TokenContext.getToken();
        ResponseEntity<WineResponse> response =
                restTemplate.postForEntity(RED_WINE, requestEntity, WineResponse.class);
        //log.info("response, {}", response);
        return response.getBody();
    }

    // 获取菜品信息
    @Override
    public FoodResponse food(String filePath) throws IOException {
        HttpEntity<MultiValueMap<String, String>> requestEntity = getMultiValueMapHttpEntity(filePath);
        FOOD = FOOD + "?access_token=" + TokenContext.getToken();
        ResponseEntity<FoodResponse> response =
                restTemplate.postForEntity(FOOD, requestEntity, FoodResponse.class);
        //log.info("response, {}", response);
        return response.getBody();
    }

    // 通用文字识别
    @Override
    public WordResponse word(String apiUrl,WordRequest request, String filePath) throws IOException {
        byte[] imgData = FileUtils.readFileByBytes(filePath);
        String imgStr = Base64Util.encodeBase64(imgData);
        MultiValueMap<String, String> postParameters = new LinkedMultiValueMap<>();
        postParameters.add("image", imgStr);
        postParameters.add("paragraph", String.valueOf(request.isParagraph()));
        postParameters.add("language_type", String.valueOf(request.getLanguageType()));
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(APPLICATION_FORM_URLENCODED);

        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(postParameters, headers);
        apiUrl = apiUrl + "?access_token=" + TokenContext.getToken();
        ResponseEntity<WordResponse> response =
                restTemplate.postForEntity(apiUrl, requestEntity, WordResponse.class);
        // log.info("response, {}", response);
        return response.getBody();
    }

    private HttpEntity<MultiValueMap<String, String>> getMultiValueMapHttpEntity(String filePath) throws IOException {
        byte[] imgData = FileUtils.readFileByBytes(filePath);
        String imgStr = Base64Util.encodeBase64(imgData);
        MultiValueMap<String, String> postParameters = new LinkedMultiValueMap<>();
        postParameters.add("image", imgStr);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(APPLICATION_FORM_URLENCODED);

        return new HttpEntity<>(postParameters, headers);
    }

    // Content-Type为application/x-www-form-urlencoded，然后通过urlencode格式化请求体
    @Override
    public TextCensorResponse textCensor(String text){
        TEXT_CENSOR = TEXT_CENSOR + "?access_token=" + TokenContext.getToken();
        MultiValueMap<String, String> postParameters = new LinkedMultiValueMap<>();
        postParameters.add("text", text);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(APPLICATION_FORM_URLENCODED);

        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(postParameters, headers);

        ResponseEntity<TextCensorResponse> response =
                restTemplate.postForEntity(TEXT_CENSOR, requestEntity, TextCensorResponse.class);
        log.info("response, {}", response);
        return response.getBody();
    }

    private byte[] getFileContent(String filename) throws IOException {
        File file = new File(filename);
        if (!file.canRead()) {
            System.err.println("文件不存在或者不可读: " + file.getAbsolutePath());
        }
        FileInputStream is = null;
        try {
            is = new FileInputStream(file);
            return ConnUtil.getInputStreamContent(is);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    private String base64Encode(byte[] content) {
        Base64.Encoder encoder = Base64.getEncoder(); // JDK 1.8  推荐方法
        String str = encoder.encodeToString(content);
        return str;
    }

    // Content-Type	application/json
    @Override
    public SearchNewsResponse searchNews(SearchNewsRequest request) {
        SEARCH_NEWS = SEARCH_NEWS + "?access_token=" + TokenContext.getToken()+ "&charset=UTF-8";
        JSONObject json = new JSONObject();
        json.put("title", request.getQuery());

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(APPLICATION_JSON);
        HttpEntity<String> requestEntity = new HttpEntity<>(json.toString(), headers);

        ResponseEntity<SearchNewsResponse> response =
            restTemplate.postForEntity(SEARCH_NEWS, requestEntity, SearchNewsResponse.class);
        return response.getBody();
    }
}

